import { Injectable, ExecutionContext, Logger, UnauthorizedException, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { SKIP_AUTH_KEY, ROLES_KEY } from '../decorators/roles.decorator';
import { SecurityEventEmitter } from '../../modules/security-log/events/security-event.emitter';

/**
 * 全局认证守卫
 * 功能：
 * 1. JWT 令牌验证
 * 2. 角色权限检查
 * 3. 跳过认证接口处理
 * 4. 详细的日志记录
 * 5. 安全事件记录
 */
@Injectable()
export class GlobalAuthGuard extends AuthGuard('jwt') {
  private readonly logger = new Logger(GlobalAuthGuard.name);

  constructor(
    private reflector: Reflector,
    private readonly securityEventEmitter: SecurityEventEmitter,
  ) {
    super();
  }

  /**
   * 检查是否可以激活路由
   * @param context 执行上下文
   * @returns 是否允许访问
   */
  canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    const authHeader = request.headers.authorization;
    
    this.logger.debug(`=== GlobalAuthGuard.canActivate 开始 ===`);
    this.logger.debug(`请求路径: ${request.url}`);
    this.logger.debug(`请求方法: ${request.method}`);
    this.logger.debug(`Authorization头: ${authHeader ? '存在' : '不存在'}`);
    
    // 检查是否需要跳过认证
    const skipAuth = this.reflector.getAllAndOverride<boolean>(SKIP_AUTH_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (skipAuth) {
      this.logger.debug('跳过身份验证，允许访问');
      this.logger.debug('=== GlobalAuthGuard.canActivate 结束 (跳过认证) ===');
      return true;
    }
    
    // 检查是否有认证头
    if (!authHeader) {
      this.logger.warn('缺少Authorization头');
      this.logger.debug('=== GlobalAuthGuard.canActivate 结束 (缺少Authorization头) ===');
      
      // 记录未授权访问事件
      this.securityEventEmitter.emitUnauthorizedAccess({
        eventTitle: '缺少认证令牌',
        eventDescription: '用户尝试访问需要认证的资源，但未提供认证令牌',
        ipAddress: this.getClientIP(request),
        userAgent: request.headers['user-agent'],
        requestUrl: request.url,
        requestMethod: request.method,
        additionalInfo: { reason: '缺少Authorization头' },
      });
      
      throw new UnauthorizedException('缺少认证令牌');
    }
    
    if (!authHeader.startsWith('Bearer ')) {
      this.logger.warn('Authorization头格式错误，应为Bearer格式');
      this.logger.debug('=== GlobalAuthGuard.canActivate 结束 (格式错误) ===');
      
      // 记录未授权访问事件
      this.securityEventEmitter.emitUnauthorizedAccess({
        eventTitle: '认证令牌格式错误',
        eventDescription: '用户提供的认证令牌格式不正确',
        ipAddress: this.getClientIP(request),
        userAgent: request.headers['user-agent'],
        requestUrl: request.url,
        requestMethod: request.method,
        additionalInfo: { reason: 'Authorization头格式错误' },
      });
      
      throw new UnauthorizedException('认证令牌格式错误');
    }
    
    this.logger.debug('=== GlobalAuthGuard.canActivate 结束 (继续验证) ===');
    return super.canActivate(context);
  }

  /**
   * 处理认证结果
   * @param err 错误信息
   * @param user 用户信息
   * @param info 额外信息
   * @param context 执行上下文
   * @returns 用户信息或抛出异常
   */
  handleRequest(err: any, user: any, info: any, context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    
    this.logger.debug(`=== GlobalAuthGuard.handleRequest 开始 ===`);
    this.logger.debug(`错误: ${err ? err.message : '无'}`);
    this.logger.debug(`用户: ${user ? '存在' : '不存在'}`);
    this.logger.debug(`信息: ${info ? info.message : '无'}`);
    
    if (err || !user) {
      const errorMessage = err?.message || info?.message || '用户不存在';
      this.logger.warn(`JWT验证失败: ${errorMessage}`);
      this.logger.debug('=== GlobalAuthGuard.handleRequest 结束 (验证失败) ===');
      
      // 记录认证失败事件
      this.securityEventEmitter.emitAuthFailed({
        eventTitle: 'JWT验证失败',
        eventDescription: `JWT令牌验证失败: ${errorMessage}`,
        ipAddress: this.getClientIP(request),
        userAgent: request.headers['user-agent'],
        requestUrl: request.url,
        requestMethod: request.method,
        errorMessage,
        additionalInfo: { reason: 'JWT验证失败' },
      });
      
      throw new UnauthorizedException('认证失败');
    }
    
    // 检查角色权限
    const requiredRoles = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    this.logger.debug(`Required roles: ${JSON.stringify(requiredRoles)}`);

    // 如果没有指定角色要求，仅需要登录即可
    if (!requiredRoles || requiredRoles.length === 0) {
      this.logger.debug('No specific roles required, allowing access');
      this.logger.debug(`用户验证成功: ${user.username}`);
      this.logger.debug('=== GlobalAuthGuard.handleRequest 结束 (验证成功) ===');
      return user;
    }

    // 检查用户角色是否满足要求
    // 注意：当前用户实体中没有roles字段，我们假设所有已认证用户都有访问权限
    // 如果将来需要实现角色功能，需要在用户实体中添加roles字段
    this.logger.debug('Role checking is not implemented yet. All authenticated users are allowed.');
    this.logger.debug(`用户验证成功: ${user.username}`);
    this.logger.debug('=== GlobalAuthGuard.handleRequest 结束 (验证成功) ===');
    return user;
  }

  /**
   * 获取客户端IP地址
   */
  private getClientIP(request: any): string {
    return (
      request.headers['x-forwarded-for'] ||
      request.headers['x-real-ip'] ||
      request.connection?.remoteAddress ||
      request.socket?.remoteAddress ||
      request.ip ||
      'unknown'
    );
  }
}
